package com.yourcompany.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yourcompany.api.dto.CreditActivateDTO;
import com.yourcompany.api.dto.CreditPayDTO;
import com.yourcompany.api.dto.CreditRepayDTO;
import com.yourcompany.api.entity.CreditPay;
import com.yourcompany.api.entity.CreditRepayment;
import com.yourcompany.api.mapper.CreditPayMapper;
import com.yourcompany.api.service.CreditPayService;
import com.yourcompany.api.service.CreditRepaymentService;
import com.yourcompany.api.service.WxPayService;
import com.yourcompany.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
@Service
public class CreditPayServiceImpl extends ServiceImpl<CreditPayMapper, CreditPay> 
        implements CreditPayService {
    
    @Autowired
    private CreditRepaymentService creditRepaymentService;
    
    @Autowired
    private WxPayService wxPayService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activate(CreditActivateDTO activateDTO) {
        // 检查用户是否已开通
        CreditPay creditPay = getById(activateDTO.getUserId());
        if (creditPay != null) {
            throw new BusinessException("已开通先充后付");
        }
        
        // 计算初始额度
        BigDecimal initialLimit = calculateInitialLimit(activateDTO);
        
        // 创建先充后付账户
        creditPay = new CreditPay();
        creditPay.setUserId(activateDTO.getUserId());
        creditPay.setCreditLimit(initialLimit);
        creditPay.setUsedCredit(BigDecimal.ZERO);
        creditPay.setAvailableCredit(initialLimit);
        creditPay.setCreditScore(100);
        creditPay.setStatus(1);
        creditPay.setActivateTime(LocalDateTime.now());
        
        save(creditPay);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String pay(CreditPayDTO payDTO) {
        // 检查额度是否足够
        if (!checkCreditAvailable(payDTO.getUserId(), payDTO.getAmount())) {
            throw new BusinessException("可用额度不足");
        }
        
        // 扣减额度
        CreditPay creditPay = getById(payDTO.getUserId());
        creditPay.setUsedCredit(creditPay.getUsedCredit().add(payDTO.getAmount()));
        creditPay.setAvailableCredit(creditPay.getCreditLimit().subtract(creditPay.getUsedCredit()));
        updateById(creditPay);
        
        // 创建还款记录
        CreditRepayment repayment = new CreditRepayment();
        repayment.setUserId(payDTO.getUserId());
        repayment.setBillMonth(getCurrentBillMonth());
        repayment.setAmount(payDTO.getAmount());
        repayment.setPaidAmount(BigDecimal.ZERO);
        repayment.setStatus(0);
        repayment.setDueDate(calculateDueDate());
        
        creditRepaymentService.createRepayment(repayment);
        
        return "success";
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String repay(CreditRepayDTO repayDTO) {
        // 获取还款记录
        CreditRepayment repayment = creditRepaymentService.getById(repayDTO.getRepaymentId());
        if (repayment == null) {
            throw new BusinessException("还款记录不存在");
        }
        
        // 调用微信支付
        String result = wxPayService.pay(repayDTO);
        
        // 更新还款记录
        repayment.setPaidAmount(repayment.getPaidAmount().add(repayDTO.getAmount()));
        repayment.setStatus(calculateRepaymentStatus(repayment));
        repayment.setPayTime(LocalDateTime.now());
        repayment.setPayMethod("微信支付");
        repayment.setTradeNo(result);
        
        creditRepaymentService.updateRepayment(repayment);
        
        // 更新可用额度
        CreditPay creditPay = getById(repayDTO.getUserId());
        creditPay.setUsedCredit(creditPay.getUsedCredit().subtract(repayDTO.getAmount()));
        creditPay.setAvailableCredit(creditPay.getCreditLimit().subtract(creditPay.getUsedCredit()));
        creditPay.setLastRepayTime(LocalDateTime.now());
        
        updateById(creditPay);
        
        return result;
    }
    
    @Override
    public BigDecimal getAvailableCredit(Long userId) {
        CreditPay creditPay = getById(userId);
        return creditPay != null ? creditPay.getAvailableCredit() : BigDecimal.ZERO;
    }
    
    @Override
    public boolean checkCreditAvailable(Long userId, BigDecimal amount) {
        CreditPay creditPay = getById(userId);
        return creditPay != null 
            && creditPay.getStatus() == 1 
            && creditPay.getAvailableCredit().compareTo(amount) >= 0;
    }

    @Override
    public CreditPay getByUserId(Long userId) {
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }
        
        // 使用 lambdaQuery 查询用户的先充后付信息
        return lambdaQuery()
                .eq(CreditPay::getUserId, userId)
                .one();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkAndHandleOverdue() {
        // 获取所有未还清的还款记录
        LambdaQueryWrapper<CreditRepayment> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(CreditRepayment::getDueDate, LocalDateTime.now())  // 已过期
                .ne(CreditRepayment::getStatus, 2);  // 未还清
        List<CreditRepayment> overdueList = creditRepaymentService.list(wrapper);
        
        for (CreditRepayment repayment : overdueList) {
            try {
                // 获取用户的先充后付信息
                CreditPay creditPay = getByUserId(repayment.getUserId());
                if (creditPay == null) {
                    continue;
                }
                
                // 更新用户信用状态
                creditPay.setStatus(0); // 设置为禁用状态
                creditPay.setUpdateTime(LocalDateTime.now());
                updateById(creditPay);
                
                // 更新还款记录状态
                repayment.setStatus(3); // 设置为逾期状态
                creditRepaymentService.updateById(repayment);
                
                // TODO: 发送逾期通知
                
                log.info("处理逾期账单：userId={}, billMonth={}", repayment.getUserId(), repayment.getBillMonth());
            } catch (Exception e) {
                log.error("处理逾期账单异常：userId=" + repayment.getUserId(), e);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void autoAdjustCreditLimit() {
        // 获取所有启用状态的先充后付用户
        List<CreditPay> creditPayList = lambdaQuery()
                .eq(CreditPay::getStatus, 1)
                .list();
        
        for (CreditPay creditPay : creditPayList) {
            try {
                // 获取用户最近3个月的还款记录
                LocalDateTime threeMonthsAgo = LocalDateTime.now().minusMonths(3);
                LambdaQueryWrapper<CreditRepayment> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(CreditRepayment::getUserId, creditPay.getUserId())
                        .ge(CreditRepayment::getCreateTime, threeMonthsAgo)
                        .orderByDesc(CreditRepayment::getCreateTime);
                List<CreditRepayment> repaymentList = creditRepaymentService.list(wrapper);
                
                // 计算信用评分
                int score = calculateCreditScore(repaymentList);
                
                // 根据信用评分调整额度
                BigDecimal newLimit = calculateNewLimit(creditPay.getCreditLimit(), score);
                
                // 更新信用额度
                creditPay.setCreditLimit(newLimit);
                creditPay.setUpdateTime(LocalDateTime.now());
                updateById(creditPay);
                
                log.info("调整信用额度：userId={}, oldLimit={}, newLimit={}", 
                        creditPay.getUserId(), creditPay.getCreditLimit(), newLimit);
            } catch (Exception e) {
                log.error("调整信用额度异常：userId=" + creditPay.getUserId(), e);
            }
        }
    }

    /**
     * 计算信用评分
     * 根据还款记录计算用户的信用评分
     */
    private int calculateCreditScore(List<CreditRepayment> repaymentList) {
        int baseScore = 60; // 基础分
        
        if (repaymentList.isEmpty()) {
            return baseScore;
        }
        
        // 统计按时还款次数
        long onTimeCount = repaymentList.stream()
                .filter(r -> r.getStatus() == 2 && r.getPayTime().isBefore(r.getDueDate()))
                .count();
        
        // 统计逾期次数
        long overdueCount = repaymentList.stream()
                .filter(r -> r.getStatus() == 3)
                .count();
        
        // 计算评分
        int score = baseScore;
        score += onTimeCount * 10;  // 每次按时还款加10分
        score -= overdueCount * 20; // 每次逾期扣20分
        
        return Math.min(Math.max(score, 0), 100); // 确保分数在0-100之间
    }

    /**
     * 计算新的信用额度
     * 根据当前额度和信用评分计算新的额度
     */
    private BigDecimal calculateNewLimit(BigDecimal currentLimit, int score) {
        if (score < 60) {
            // 信用评分过低，降低额度
            return currentLimit.multiply(new BigDecimal("0.8"));
        } else if (score >= 90) {
            // 信用评分很高，提高额度
            return currentLimit.multiply(new BigDecimal("1.2"));
        } else if (score >= 80) {
            // 信用评分较高，小幅提高额度
            return currentLimit.multiply(new BigDecimal("1.1"));
        }
        // 信用评分一般，维持现有额度
        return currentLimit;
    }

    private BigDecimal calculateInitialLimit(CreditActivateDTO activateDTO) {
        // TODO: 根据用户信用评分等计算初始额度
        return new BigDecimal("500");
    }
    
    private String getCurrentBillMonth() {
        // 获取当前账单月份，格式：yyyy-MM
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
    }
    
    private LocalDateTime calculateDueDate() {
        // 计算还款日期，默认下个月10号
        return LocalDateTime.now()
            .plusMonths(1)
            .withDayOfMonth(10)
            .withHour(23)
            .withMinute(59)
            .withSecond(59);
    }
    
    private int calculateRepaymentStatus(CreditRepayment repayment) {
        if (repayment.getPaidAmount().compareTo(repayment.getAmount()) >= 0) {
            return 2; // 已还清
        } else if (repayment.getPaidAmount().compareTo(BigDecimal.ZERO) > 0) {
            return 1; // 部分还款
        }
        return 0; // 未还款
    }
} 